﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace Common
{
    /// <summary>
    /// 校验使用时间
    /// </summary>
    public class License
    {
        /// <summary>
        /// 加密字符串
        /// </summary>
        public static string EncryptedString { get; set; }

        private static string key;

        /// <summary>
        /// 密钥
        /// </summary>
        public static string Key
        {
            get { return key; }
            set { key = "BOJ2020-" + value; }
        }

        /// <summary>
        /// 上一次登录的时间
        /// </summary>
        private static Int64 LastLoginDateTime;

        private static Int64 PermissionDateTime;

        private static string LicenseFilePath = Environment.CurrentDirectory + @"\license.txt";

        /// <summary>
        /// 从文件获取SN
        /// </summary>
        /// <param name="snFilePath"> </param>
        /// <returns> </returns>
        /// <exception cref="Exception"> </exception>
        public static string GetSN(string snFilePath)
        {
            if (string.IsNullOrEmpty(snFilePath))
                throw new Exception("设备SN文件路径不能为空");
            if (!File.Exists(snFilePath))
                throw new Exception("设备SN文件不存在");

            string sn = null;
            using (StreamReader reader = new StreamReader(snFilePath))
            {
                // 读取文件的每一行，直到文件末尾
                while (!reader.EndOfStream)
                {
                    sn += reader.ReadLine(); // 读取一行文本
                }
            }
            Key = sn;
            return sn;
        }

        /// <summary>
        /// 读取本地的上次登录时间和许可证有效期
        /// </summary>
        public static bool Check(out string msg)
        {
            try
            {
                var dateStr = ReadLicenseFile();
                if (dateStr.Length != 28)
                {
                    throw new Exception("License数据异常");
                }
                string firstHalf = dateStr.Substring(0, 14);
                string secondHalf = dateStr.Substring(14);
                if (!Int64.TryParse(firstHalf, out LastLoginDateTime))
                {
                    throw new Exception("License数据异常");
                }
                if (!Int64.TryParse(secondHalf, out PermissionDateTime))
                {
                    throw new Exception("License数据异常");
                }

                var loginDateTime = FormatDatetime(DateTime.Now);
                if (loginDateTime <= LastLoginDateTime)
                {
                    throw new Exception("登录时间早于上次登录时间,请同步网络时间");
                }
                if (loginDateTime > PermissionDateTime)
                {
                    throw new Exception("超过有效许可时间,请联系供应商获取许可证");
                }
                LastLoginDateTime = loginDateTime;
                SetLicenseFile();
                var tmp = PermissionDateTime.ToString();

                var diff = (new DateTime(int.Parse(tmp.Substring(0, 4)), int.Parse(tmp.Substring(4, 2)), int.Parse(tmp.Substring(6, 2))) - DateTime.Today).TotalDays;

                //msg = $"软件授权到期时间为{tmp.Substring(0, 4)}-{tmp.Substring(4, 2)}-{tmp.Substring(6, 2)}，还剩{diff}天";
                msg = $"{tmp.Substring(0, 4)}-{tmp.Substring(4, 2)}-{tmp.Substring(6, 2)},{diff}";
                return true;
            }
            catch (Exception ex)
            {
                msg = ex.Message;
                return false;
            }
        }

        private static string ReadLicenseFile()
        {
            if (!File.Exists("License.txt"))
            {
                throw new Exception("License文件丢失");
            }
            try
            {
                using (FileStream fileStream = new FileStream(LicenseFilePath, FileMode.Open))
                {
                    using (BinaryReader reader = new BinaryReader(fileStream))
                    {
                        byte[] data = reader.ReadBytes((int)fileStream.Length);
                        return Decrypt(Encoding.UTF8.GetString(data), key);
                    }
                }
            }
            catch (Exception)
            {
                throw new Exception("License数据格式错误");
            }
        }

        private static void SetLicenseFile()
        {
            EncryptedString = Encrypt(LastLoginDateTime.ToString() + PermissionDateTime.ToString(), key);

            byte[] byteArray = Encoding.UTF8.GetBytes(EncryptedString);
            using (FileStream fileStream = new FileStream(LicenseFilePath, FileMode.Create))
            {
                using (BinaryWriter writer = new BinaryWriter(fileStream))
                {
                    writer.Write(byteArray);
                }
            }
        }

        /// <summary>
        /// 生成license文件
        /// </summary>
        /// <param name="dateTime"> </param>
        public static void GenrateLiceseFile(DateTime dateTime)
        {
            LastLoginDateTime = FormatDatetime(DateTime.Now);
            PermissionDateTime = FormatDatetime(dateTime);
            SetLicenseFile();
        }

        private static Int64 FormatDatetime(DateTime date)
        {
            return Convert.ToInt64(date.ToString("yyyyMMddHHmmss"));
        }

        /// <summary>
        /// 加密算法
        /// </summary>
        /// <param name="plaintext"> </param>
        /// <param name="key">       </param>
        /// <returns> </returns>
        public static string Encrypt(string plaintext, string key)
        {
            byte[] encryptedBytes;

            using (Aes aesAlg = Aes.Create())
            {
                aesAlg.Key = Encoding.UTF8.GetBytes(key);
                aesAlg.Mode = CipherMode.ECB; // 设置加密模式为 ECB，注意 ECB 模式不是最安全的模式，仅供示例
                ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);

                using (MemoryStream msEncrypt = new MemoryStream())
                {
                    using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
                    {
                        using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
                        {
                            swEncrypt.Write(plaintext);
                        }
                        encryptedBytes = msEncrypt.ToArray();
                    }
                }
            }

            return Convert.ToBase64String(encryptedBytes);
        }

        /// <summary>
        /// 解密算法
        /// </summary>
        /// <param name="ciphertext"> </param>
        /// <param name="key">        </param>
        /// <returns> </returns>
        public static string Decrypt(string ciphertext, string key)
        {
            byte[] cipherBytes = Convert.FromBase64String(ciphertext);
            string plaintext = null;

            using (Aes aesAlg = Aes.Create())
            {
                aesAlg.Key = Encoding.UTF8.GetBytes(key);
                aesAlg.Mode = CipherMode.ECB; // 设置加密模式为 ECB，注意 ECB 模式不是最安全的模式，仅供示例
                ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);

                using (MemoryStream msDecrypt = new MemoryStream(cipherBytes))
                {
                    using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
                    {
                        using (StreamReader srDecrypt = new StreamReader(csDecrypt))
                        {
                            plaintext = srDecrypt.ReadToEnd();
                        }
                    }
                }
            }

            return plaintext;
        }
    }
}